package com.jinunn.system.secutity.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import com.jinunn.system.common.constant.JwtClaimConstants;
import com.jinunn.system.secutity.model.SysUserDetail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * JWT 工具类
 *
 * @author Jindun
 * @version JwtUtils.java, v0.1 2024年 07⽉ 10⽇  下午5:37 Jindun Exp $
 */
@Component
public class JwtUtils {

    /**
     * JWT 加解密使用的密钥
     */
    private static byte[] key;

    /**
     * JWT Token 的有效时间(单位:秒)
     */
    private static int ttl;

    @Value("${security.jwt.key}")
    public void setKey(String key) {
        JwtUtils.key = key.getBytes();
    }

    @Value("${security.jwt.ttl}")
    public void setTtl(Integer ttl) {
        JwtUtils.ttl = ttl;
    }

    /**
     * 生成 JWT Token
     *
     * @param authentication 用户认证信息
     * @return Token 字符串
     */
    public static String createToken(Authentication authentication) {
        SysUserDetail userDetails = (SysUserDetail) authentication.getPrincipal();
        // claims 中添加角色信息
        Set<String> roles = userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toSet());
        Map<String, Object> payload = new HashMap<>();
        // 用户ID
        payload.put(JwtClaimConstants.USER_ID, userDetails.getUserId());
        // 部门ID
        payload.put(JwtClaimConstants.DEPT_ID, userDetails.getDeptId());
        // 数据权限范围
        payload.put(JwtClaimConstants.DATA_SCOPE, userDetails.getDataScope());
        // 角色
        payload.put(JwtClaimConstants.AUTHORITIES, roles);

        Date now = new Date();
        Date expiration = DateUtil.offsetSecond(now, ttl);
        payload.put(JWTPayload.ISSUED_AT, now);
        // 过期时间
        payload.put(JWTPayload.EXPIRES_AT, expiration);
        // 用户名
        payload.put(JWTPayload.SUBJECT, authentication.getName());
        // JWT_ID
        payload.put(JWTPayload.JWT_ID, IdUtil.simpleUUID());
        return JWTUtil.createToken(payload, key);
    }

    /**
     * 从 JWT Token 中解析 Authentication  用户认证信息
     *
     * @param payloads JWT 载体
     * @return 用户认证信息
     */
    public static UsernamePasswordAuthenticationToken getAuthentication(JSONObject payloads) {
        SysUserDetail userDetails = new SysUserDetail();
        // 用户ID
        userDetails.setUserId(payloads.getLong(JwtClaimConstants.USER_ID));
        // 部门ID
        userDetails.setDeptId(payloads.getLong(JwtClaimConstants.DEPT_ID));
        // 数据权限范围
        userDetails.setDataScope(payloads.getInt(JwtClaimConstants.DATA_SCOPE));
        // 用户名
        userDetails.setUsername(payloads.getStr(JWTPayload.SUBJECT));
        // 角色集合
        Set<SimpleGrantedAuthority> authorities = payloads.getJSONArray(JwtClaimConstants.AUTHORITIES)
                .stream()
                .map(authority -> new SimpleGrantedAuthority(Convert.toStr(authority)))
                .collect(Collectors.toSet());
        return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);
    }
}
